﻿/*  
 @author : Song Jiaqi 
 @date : 2022-05-18 21:33  
*/

/*---扑克牌游戏---
 * 游戏规则：
 *
 * */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/*定义玩家*/
int p1; //玩家一
int p2; //玩家二


/*定义卡牌*/
int card[5][2]; //总牌数
int player1Card[5]; //玩家一的牌数
int player2Card[5]; //玩家二的牌数

/*记录得分*/
int p1_score = 0;
int p2_score = 0;

typedef struct node {
    int data;
    struct node *lChild;
    struct node *rChild;
} node;

/*游戏规则*/
void gameRules() {
    printf("\n游戏规则如下：\n");
    printf("0.游戏玩法为：通过扑克牌上的数字进行比大小，去除大王小王，A,J,Q,K分别用1,11,12,13代替。\n");
    printf("1.游戏以两位玩家对决展开，每局两位玩家都会发到5张牌，玩家一先出牌，玩家二后出牌。\n");
    printf("2.每回合(共五回合)玩家各出一张牌进行比大小，大者赢得本回合胜利。\n");
    printf("3.最先将手中卡牌出完的玩家获得本局胜利，本局游戏结束后玩家可选择进行下一局游戏或者结算比分。\n\n");
}


/*建立平衡二叉树*/
node *tree_Insert(node *t, int key) {
    //头结点为空，将当前结点设置为根节点
    if (t == NULL) {
        node *p;
        p = (node *) malloc(sizeof(node));
        p->data = key;
        p->lChild = NULL;
        p->rChild = NULL;
        t = p;
    } else {
        //头结点不为空，进行插入操作
        if (key < t->data) {
            //小于根结点，插入左子树
            t->lChild = tree_Insert(t->lChild, key);
        } else {
            //大于或等于根结点，插入右子树
            t->rChild = tree_Insert(t->rChild, key);
        }
    }
    return t;
}

/*将玩家一的手牌存储到平衡树*/
node *p1_save(node *t) {
    int i, key;
    for (i = 0; i < 5; i++) {
        key = player1Card[i];
        t = tree_Insert(t, key);
    }
    return t;
}

/*将玩家二的手牌存储到平衡树*/
node *p2_save(node *t) {
    int i, key;
    for (i = 0; i < 5; i++) {
        key = player2Card[i];
        t = tree_Insert(t, key);
    }
    return t;
}

/*先序遍历输出玩家手牌*/
void Pre_sort(node *t) {
    if (t != NULL) {
        Pre_sort(t->lChild);
        printf("%d ", t->data);
        Pre_sort(t->rChild);
    }
}

/*开始游戏*/
void startGame() {
    int i;
    node *t1 = NULL;
    node *t2 = NULL;
    //发牌
    for (i = 0; i < 5; i++) {
        printf("---第%d次发牌---\n", i + 1);
        p1 = rand() % 13 + 1;
        p2 = rand() % 13 + 1;
        printf("玩家一发到的牌为：%d\n", p1);
        player1Card[i] = p1;
        printf("玩家二发到的牌为：%d\n", p2);
        player2Card[i] = p2;
        printf("\n");
    }

    //建立玩家一平衡二叉树
    t1 = p1_save(t1);
    printf("玩家一的手牌为：");
    Pre_sort(t1);
    printf("\n");
    //建立玩家二平衡二叉树
    t2 = p2_save(t2);
    printf("玩家二的手牌为：");
    Pre_sort(t2);
    printf("\n\n");
}

/*开始出牌*/
void sendPoker() {
    int p1_pokerNum = 0;
    int p2_pokerNum = 0;
    int n = 0, m;
    p1 = p2 = 0;
    //从玩家一和二的五张牌中进行比大小
    for (n; n < 5; n++) {
        printf("\n---第%d回合开始---\n", n + 1);
        /*p1出牌*/
        if (card[n][0] == 0) {
            printf("玩家一出牌%d\n", player1Card[n]);
        }
        if (player2Card[n] > player1Card[n] && card[n][1] == 0) {
            /*p2出牌*/
            printf("玩家二出牌%d\n", player2Card[n]);
            p2 = player2Card[n];
            card[n][1] = 1;
            p2_pokerNum++;
            printf("\n玩家二赢得本回合胜利!\n");
        } else if (player2Card[n] == player1Card[n] && card[n][1] == 0) {
            printf("玩家二出牌%d\n", player2Card[n]);
            printf("\n玩家打成平局\n");
            p1_pokerNum++;
            p2_pokerNum++;
            card[n][0] = 1;
            card[n][1] = 1;
        } else if (player2Card[n] < player1Card[n] && card[n][1] == 0) {
            printf("玩家二不出牌\n");
            p1 = player1Card[n];
            card[n][0] = 1;
            p1_pokerNum++;
            printf("\n玩家一赢得本回合胜利!\n");
        }

        //置零胜者最大牌,为下一回合做准备
        if (p1 > p2) {
            p1 = 0;
        } else if (p1 < p2) {
            p2 = 0;
        } else if (p1 == p2) {
            p1 = 0;
            p2 = 0;
        }

        printf("---第%d回合结束---\n\n", n + 1);
    }

    /*牌出完后退出循环*/
    if (p1_pokerNum != 5 && p2_pokerNum != 5) {
        //打出的牌越多，说明手牌越少
        if (p1_pokerNum > p2_pokerNum) {
            printf("玩家一剩余手牌最少，玩家一赢得本局游戏的胜利！\n\n");
            p1_score++;
        } else if (p1_pokerNum == p2_pokerNum) {
            printf("玩家一和玩家二不分上下，打成平局！\n\n");
            p1_score++;
            p2_score++;
        } else {
            printf("玩家二剩余手牌最少，玩家二赢得本局游戏的胜利！\n\n");
            p2_score++;
        }
    }

    /*极端情况*/
    //p1五连胜
    if (p1_pokerNum == 5) {
        printf("玩家一完胜，拿下五连胜！\n\n");
        p1_score++;
    }
    //p2五连胜
    if (p2_pokerNum == 5) {
        printf("玩家二完胜，拿下五连胜！\n\n");
        p2_score++;
    }



    /*重置卡牌标记状态，为下一局游戏做准备*/
    for (n = 0; n < 5; n++) {
        card[n][0] = 0;
        card[n][1] = 0;
    }

    /*是否开启下局游戏*/
    printf("是否继续下一局游戏？\n");
    printf("1.是，继续游戏\n");
    printf("2.否，结算得分\n");
    scanf("%d", &m);
    switch (m) {
        case 1:
            startGame();
            break;
        case 2:
            /*设置比赛比分*/
            printf("\n最终游戏比分为：\n");
            printf("玩家一：玩家二 = %d : %d \n\n", p1_score, p2_score);
            /*数据清零*/
            p1_score = 0;
            p2_score = 0;
            break;
        default:
            printf("操作异常，游戏异常退出\n\n");
            exit(0);
    }


}

/*主函数*/
int main() {
    /*字符界面*/
    int n;
    int flag = 1;
    /*改变每次生成的随机数，将时间作为种子*/
    srand((unsigned) time(NULL));
    printf("--------------欢迎来到扑克牌游戏!--------------\n");
    printf("作者：宋嘉骐         20201209619\n\n");
    while (flag) {
        printf("**************************\n");
        printf(" 请选择您的操作：\n");
        printf(" *  1.游戏规则  *\n");
        printf(" *  2.开始游戏  *\n");
        printf(" *  3.开始出牌  *\n");
        printf(" *  4.退出游戏  *\n");
        printf("**************************\n");
        printf("在此输入数字：");
        scanf("%d", &n);
        switch (n) {
            case 1:
                gameRules();
                break;
            case 2:
                startGame();
                break;
            case 3:
                sendPoker();
                break;
            case 4:
                printf("--------------游戏已退出，欢迎下次游玩!-----------\n");
                flag = 0;
                break;
            default:
                printf("您的操作有误，请输入1-4之间的数字！\n\n");
                break;
        }
    }
    return 1;
}



